package com.project.lk.nurseapp.babyvoice;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Paint;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.util.Log;
import android.view.SurfaceView;

import com.project.lk.nurseapp.base.BaseApp;

import java.io.FileOutputStream;
import java.util.ArrayList;

/**
 * 功能介绍：
 * 项目名：
 * 模块名称：
 * 作者：LK
 * 日期：2018/1/3
 * 修改日期：
 */

@SuppressLint("NewApi")
public class SoundCard {
    private final static String TAG = SoundCard.class.getSimpleName();

    //private  boolean isInitialized = false;

    private int mMode = 0;

    FileOpration FileOp;
    String SDPath;
    FileOutputStream mRevDataFileStream;



    private int mSampleFrequency = 1000;//采样的频率
    private int mFrequency = 8000;//播放的频率  只支持4000Hz到48000Hz之间
    private int mFreDiff = mFrequency / mSampleFrequency;

    private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; //CHANNEL_OUT_DEFAULT
    private int mAudioEncoding = AudioFormat.ENCODING_PCM_16BIT;

    public long mTestPlayDatas = 0;

    AudioRecord mAudioRecord;
    AudioTrack mAudioTrack;
    AudioManager mAudioManager;

    public int mRecBufSize, mPlayBufSize;//录音最小buffer大小

    private ArrayList<short[]> mInBuf = new ArrayList<short[]>();
    private boolean miRecording = false;// 线程控制标记

    private int mTicks = 0;

    private int mPerFrameLastData = 0;

    private boolean miPlaying = false;// 线程控制标记
    private boolean miPlayBufValid = false;

    ///---
    private int mTimesPerFrame = 50;//50ms一帧

    private int mPlayBufLenPerFrame = mTimesPerFrame * mFreDiff;

    //每个缓存存200ms的数据
    //滑动窗机制，每个窗为400ms数据，其中播放和写入数据差200ms
    private int mDatasPerFrame = mFrequency / (1000 / mTimesPerFrame);
    private int mPlayBufWindowns = 3;
    private int mPlayBufFramesPerWindown = 6;//小米的可以4，华为的必须6以上
    private int mPlayBufLen = mDatasPerFrame * mPlayBufWindowns * mPlayBufFramesPerWindown;
    private int mPlayIndex = 0;//滑动窗的细分格索引
    private int mWriteIndex = 0;//滑动窗的细分格索引
    private short[] mPlayBuf = new short[mPlayBufLen];
    ///---

    public int mTimeOutCnt = 0;

    public int mPlayCnt = 0;


    private  int mFreDoubles = 1;//只可以是1或者2
    private int mVol = 2;//1~10

    private final int mN = 100;

    short mPerDatasSrc[] = new short[mN];
    short mPerDatasFilter[] = new short[mN];

    public boolean mbCloseWavFile = false;
    private WavFileOpration mWavFileOpration;

    int mtest1 = 0;
    int mtest2 = 0;

    private double mh1[] =
            {
                    //600Hz
			/*
			-0,-5.02386e-006,-1.03158e-005,4.85288e-006,5.85787e-005,0.000152257,0.000261275,0.000335851,0.0003142,0.000145631,
			-0.000183164,-0.000628112,-0.00108326,-0.00139751,-0.00141225,-0.00101222,-0.000176227,0.00098898,0.00224596,0.00326317,
			0.00368837,0.00324527,0.00183017,-0.000418985,-0.00310594,-0.00562673,-0.00728674,-0.00746515,-0.0057922,-0.00229534,
			0.00252851,0.00774576,0.0121335,0.014424,0.0136045,0.00920825,0.0015307,-0.0082904,-0.0183666,-0.0263243,
			-0.0297082,-0.0264538,-0.0153388,0.00368104,0.0293275,0.0590904,0.0895515,0.116893,0.137505,0.148579,
			0.148579,0.137505,0.116893,0.0895515,0.0590904,0.0293275,0.00368104,-0.0153388,-0.0264538,-0.0297082,
			-0.0263243,-0.0183666,-0.0082904,0.0015307,0.00920825,0.0136045,0.014424,0.0121335,0.00774576,0.00252851,
			-0.00229534,-0.0057922,-0.00746515,-0.00728674,-0.00562673,-0.00310594,-0.000418985,0.00183017,0.00324527,0.00368837,
			0.00326317,0.00224596,0.00098898,-0.000176227,-0.00101222,-0.00141225,-0.00139751,-0.00108326,-0.000628112,-0.000183164,
			0.000145631,0.0003142,0.000335851,0.000261275,0.000152257,5.85787e-005,4.85288e-006,-1.03158e-005,-5.02386e-006,-0
			*/


                    //700Hz
                    0,6.60172e-006,2.24135e-005,2.58951e-005,-1.31774e-005,-0.000110552,-0.000245884,-0.000356538,-0.000355262,-0.000169334,
                    0.000212976,0.000710198,0.00114998,0.00131519,0.00102542,0.000227702,-0.000940352,-0.00214879,-0.00295136,-0.002928,
                    -0.00185342,0.000167554,0.002657,0.00484964,0.00590319,0.00518245,0.00252986,-0.00157637,-0.00605399,-0.00946331,
                    -0.0104246,-0.00809584,-0.00256215,0.00500784,0.0125303,0.0175013,0.0177175,0.0120358,0.00094827,-0.0132281,
                    -0.0266568,-0.0347623,-0.0333272,-0.0196421,0.0065973,0.042905,0.0842762,0.124093,0.155475,0.172761,
                    0.172761,0.155475,0.124093,0.0842762,0.042905,0.0065973,-0.0196421,-0.0333272,-0.0347623,-0.0266568,
                    -0.0132281,0.00094827,0.0120358,0.0177175,0.0175013,0.0125303,0.00500784,-0.00256215,-0.00809584,-0.0104246,
                    -0.00946331,-0.00605399,-0.00157637,0.00252986,0.00518245,0.00590319,0.00484964,0.002657,0.000167554,-0.00185342,
                    -0.002928,-0.00295136,-0.00214879,-0.000940352,0.000227702,0.00102542,0.00131519,0.00114998,0.000710198,0.000212976,
                    -0.000169334,-0.000355262,-0.000356538,-0.000245884,-0.000110552,-1.31774e-005,2.58951e-005,2.24135e-005,6.60172e-006,0


			/*
			//750
			-0,-1.91786e-006,7.82504e-006,4.78126e-005,0.000111573,0.000157486,0.000123545,-3.56315e-005,-0.000306916,-0.000596972,
			-0.000750828,-0.000613552,-0.000114926,0.000660818,0.00146074,0.00192795,0.00173626,0.000750191,-0.000857396,-0.00259414,
			-0.00377491,-0.00376388,-0.00225444,0.000523428,0.00377108,0.00631503,0.00699454,0.00512604,0.00087418,-0.00463499,
			-0.00955231,-0.0118693,-0.0101521,-0.00420002,0.00463171,0.0136231,0.0194156,0.0191058,0.011386,-0.00265355,
			-0.0193822,-0.0332911,-0.0383564,-0.0297636,-0.00550164,0.0326692,0.0792216,0.125915,0.163667,0.184754,
			0.184754,0.163667,0.125915,0.0792216,0.0326692,-0.00550164,-0.0297636,-0.0383564,-0.0332911,-0.0193822,
			-0.00265355,0.011386,0.0191058,0.0194156,0.0136231,0.00463171,-0.00420002,-0.0101521,-0.0118693,-0.00955231,
			-0.00463499,0.00087418,0.00512604,0.00699454,0.00631503,0.00377108,0.000523428,-0.00225444,-0.00376388,-0.00377491,
			-0.00259414,-0.000857396,0.000750191,0.00173626,0.00192795,0.00146074,0.000660818,-0.000114926,-0.000613552,-0.000750828,
			-0.000596972,-0.000306916,-3.56315e-005,0.000123545,0.000157486,0.000111573,4.78126e-005,7.82504e-006,-1.91786e-006,-0
			*/
            };

    private double mh2[] =
            {
                    -3.75736e-005,-0.000313198,-0.000732852,-0.00107397,-0.00111636,-0.000760194,-0.000115559,0.000505267,0.000730963,0.000365887,
                    -0.000415729,-0.001071,-0.000951298,0.000277862,0.00231314,0.00424508,0.00502143,0.00413019,0.00207909,0.000286479,
                    0.000317929,0.00284223,0.00695858,0.0104351,0.0108931,0.00733911,0.0010917,-0.00463566,-0.00648288,-0.00312988,
                    0.0034288,0.00852619,0.00732652,-0.00207688,-0.0168466,-0.0302663,-0.0352374,-0.0287025,-0.0144094,-0.00199625,
                    -0.00224874,-0.0206401,-0.0526167,-0.0836403,-0.0947731,-0.071648,-0.0125719,0.0685091,0.14621,0.19363,
                    0.19363,0.14621,0.0685091,-0.0125719,-0.071648,-0.0947731,-0.0836403,-0.0526167,-0.0206401,-0.00224874,
                    -0.00199625,-0.0144094,-0.0287025,-0.0352374,-0.0302663,-0.0168466,-0.00207688,0.00732652,0.00852619,0.0034288,
                    -0.00312988,-0.00648288,-0.00463566,0.0010917,0.00733911,0.0108931,0.0104351,0.00695858,0.00284223,0.000317929,
                    0.000286479,0.00207909,0.00413019,0.00502143,0.00424508,0.00231314,0.000277862,-0.000951298,-0.001071,-0.000415729,
                    0.000365887,0.000730963,0.000505267,-0.000115559,-0.000760194,-0.00111636,-0.00107397,-0.000732852,-0.000313198,-3.75736e-005

            };
    private double mh3[] =
            {//带通，180~2000
                    2.66e-005,8.74579e-005,-0.000631443,-0.000600684,0.000370135,0.000515019,-0.000474407,-0.000406744,0.00117669,0.00148687,
                    -8.69804e-005,5.86156e-005,0.00270446,0.00319677,0.000552097,0.000704005,0.00482445,0.00537445,0.000914909,0.000838354,
                    0.00680722,0.00714598,-0.000150754,-0.000813798,0.007464,0.00727833,-0.00411837,-0.00572049,0.0056824,0.00479456,
                    -0.0122007,-0.0149346,0.00119149,-0.000244549,-0.0248214,-0.0286532,-0.00468912,-0.00601215,-0.0416775,-0.0465563,
                    -0.00822262,-0.00789404,-0.0636123,-0.070718,0.00031372,0.00784319,-0.10628,-0.133326,0.10517,0.405102,
                    0.405102,0.10517,-0.133326,-0.10628,0.00784319,0.00031372,-0.070718,-0.0636123,-0.00789404,-0.00822262,
                    -0.0465563,-0.0416775,-0.00601215,-0.00468912,-0.0286532,-0.0248214,-0.000244549,0.00119149,-0.0149346,-0.0122007,
                    0.00479456,0.0056824,-0.00572049,-0.00411837,0.00727833,0.007464,-0.000813798,-0.000150754,0.00714598,0.00680722,
                    0.000838354,0.000914909,0.00537445,0.00482445,0.000704005,0.000552097,0.00319677,0.00270446,5.86156e-005,-8.69804e-005,
                    0.00148687,0.00117669,-0.000406744,-0.000474407,0.000515019,0.000370135,-0.000600684,-0.000631443,8.74579e-005,2.66e-005
            };

    public void setVol(int vol)
    {
        mVol = vol;
    }

    public int setVolUp()
    {
        if(mVol < 50)
        {
            mVol++;
        }
        return mVol;
    }

    public int setVolDown()
    {
        if(mVol > 1)
        {
            mVol--;
        }
        else
        {
            mVol = 1;
        }
        return mVol;
    }

    public void setFre(int fre)
    {
        if((fre >= 1) && (fre <= 2))
        {
            mFreDoubles = fre;
        }
    }

    public SoundCard( int mode, int phonePlayFre, int devSampleFre)
    {
        this.mMode = mode;
        this.mSampleFrequency = devSampleFre;
        this.mFrequency = phonePlayFre;

        //mSampleFrequency = 1000;//采样的频率
        //mFrequency = 8000;//播放的频率  只支持4000Hz到48000Hz之间
        mFreDiff = mFrequency / mSampleFrequency;

        Initial();

        if(mode == 1)
        {
            miPlaying = true;
            PlayingThread tRec = new PlayingThread();
            new Thread(tRec).start();

            new Thread(new PlayDataCheckThread()).start();
        }
        else if(mode == 2)
        {
            miRecording = true;
            //new RecordThread(mAudioRecord, mAudioTrack, mRecBufSize).start();// 开始录制线程
            RecordThread tRec = new RecordThread(mAudioRecord, mAudioTrack, mRecBufSize);
            new Thread(tRec).start();
            mAudioManager.setSpeakerphoneOn(true);
        }

        mWavFileOpration = new WavFileOpration("FilterWavFile", mFrequency);

    }

    public void Initial()
    {
        //参数初始化

        mTimesPerFrame = 50;//50ms一帧
        mPlayBufLenPerFrame = mTimesPerFrame * mFreDiff;
        //每个缓存存200ms的数据
        //滑动窗机制，每个窗为400ms数据，其中播放和写入数据差200ms
        mDatasPerFrame = mFrequency / (1000 / mTimesPerFrame);
        mPlayBufWindowns = 3;
        mPlayBufFramesPerWindown = 6;//小米的可以4，华为的必须6以上
        mPlayBufLen = mDatasPerFrame * mPlayBufWindowns * mPlayBufFramesPerWindown;
        mPlayIndex = 0;//滑动窗的细分格索引
        mWriteIndex = 0;//滑动窗的细分格索引
        mPlayBuf = new short[mPlayBufLen];



        //录音组件
        mRecBufSize = AudioRecord.getMinBufferSize(mFrequency, mChannelConfiguration, mAudioEncoding);
        mPlayBufSize= AudioTrack.getMinBufferSize(mFrequency, mChannelConfiguration, mAudioEncoding);
        mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, mFrequency, mChannelConfiguration, mAudioEncoding, mRecBufSize);
        //STREAM_MUSIC  VOICE_CALL   VOICE_COMMUNICATION   DEFAULT
        if(mMode == 1)
        {
            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mFrequency, mChannelConfiguration, mAudioEncoding, mDatasPerFrame * mPlayBufFramesPerWindown, AudioTrack.MODE_STREAM);
            //mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mFrequency, mChannelConfiguration, mAudioEncoding, mPlayBufSize, AudioTrack.MODE_STREAM);
        }
        else
        {//STREAM_SYSTEM     STREAM_VOICE_CALL
            mAudioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL, mFrequency, mChannelConfiguration, mAudioEncoding, mPlayBufSize, AudioTrack.MODE_STREAM);
        }
        //mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mFrequency, mChannelConfiguration, mAudioEncoding, mDatasPerFrame * mPlayBufFramesPerWindown, AudioTrack.MODE_STREAM);//MODE_STATIC  MODE_STREAM
        //mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mFrequency, mChannelConfiguration, mAudioEncoding, mPlayBufSize, AudioTrack.MODE_STREAM);

        mAudioManager = (AudioManager) BaseApp.getContext().getSystemService(Context.AUDIO_SERVICE);
        mAudioManager.setSpeakerphoneOn(true);//使用扬声器外放，即使已经插入耳机
        mAudioManager.setMicrophoneMute(false);
        mAudioTrack.setStereoVolume(1.0f, 1.0f);//设置当前音量大小

        int i;
        for(i = 0; i < mN; i++)
        {
            mPerDatasSrc[i] = 0;
            mPerDatasFilter[i] = 0;
        }

        FileOp = new FileOpration();
        SDPath = FileOp.getSDPath();
        //Log.i(TAG, "SDpath = " + SDPath);
        mRevDataFileStream = FileOp.CreateFile(SDPath + "/nurseApp", "FilterData.txt");
    }

    /**
     * 开始 录音
     *
     * @param recBufSize
     *            AudioRecord的MinBufferSize
     */
	/*public void StartRecord(AudioRecord audioRecord, AudioTrack audioTrack, int recBufSize, SurfaceView sfv, Paint mPaint)
	{
		if(false == miRecording)
		{
			miRecording = true;
			//new RecordThread(audioRecord, audioTrack, recBufSize).start();// 开始录制线程
			RecordThread tRec = new RecordThread(audioRecord, audioTrack, recBufSize);
			new Thread(tRec).start();

		}
	}*/
    public void StartRecord(SurfaceView sfv, Paint mPaint)
    {
        if(false == miRecording)
        {
            miRecording = true;
            //new RecordThread(audioRecord, audioTrack, recBufSize).start();// 开始录制线程
            RecordThread tRec = new RecordThread(mAudioRecord, mAudioTrack, mRecBufSize);
            new Thread(tRec).start();

        }
    }

    /**
     * 停止
     */
    public void StopRecord()
    {
        miRecording = false;
        mInBuf.clear();// 清除
    }

    /**
     * 负责从MIC保存数据到inBuf
     *
     * @author GV
     *
     */
    class RecordThread implements Runnable //extends Thread
    {
        private int recBufSize;
        private AudioRecord audioRecord;
        private AudioTrack audioTrack;
        public RecordThread(AudioRecord audioRecord, AudioTrack audioTrack, int recBufSize)
        {
            this.audioRecord = audioRecord;
            this.audioTrack = audioTrack;
            this.recBufSize = recBufSize;
        }
        public void run()
        {
            try
            {
                int i;
                short[] intdata = new short[recBufSize * 4];//不需要 *4
                short[] outdata = new short[recBufSize * 4];
                //这里需要两次调用才行，为什么？
                audioRecord.startRecording();// 开始录制
                audioRecord.startRecording();// 开始录制

                audioTrack.play();//开始播放
                audioTrack.play();//开始播放
                while (miRecording)
                {
                    // 从MIC保存数据到缓冲区
                    int bufferReadResult = audioRecord.read(intdata, 0, recBufSize);
                    Filter(intdata, outdata, mPerDatasFilter, mh3, bufferReadResult, mN, mVol);

                    Log.i(TAG, "rev data = " + outdata[0] + ", " + outdata[1] + ", " + outdata[2] + ", "
                            + outdata[3] + ", " + outdata[4] + ", " + outdata[5] + ", "
                            + outdata[6] + ", " + outdata[7] + ", " + outdata[8] + ", ");
                    ////////////////////
                    //if(mFreDoubles == 2)
                    //{
						/*for(i = 0; i < bufferReadResult; i++)
						{
							intdata[i] = (short)Math.abs(outdata[i]);
						}
						Filter(intdata, outdata, mPerDatasFilter, mh3, bufferReadResult, mN, 2);//倍频的滤波

						for(i = 0; i < mN; i++)
						{
							mPerDatasFilter[i] = intdata[bufferReadResult - mN + i];//保存滤波后的数据，做第二次滤波用
						}*/
                    //}
                    //////////////////////

                    audioTrack.write(outdata, 0, bufferReadResult);



                    //Filter(intdata, outdata, mPerDatasFilter, mh2, indataLen, mN, mVol);
                    ////////////////////////////
					/*short[] tmpBuf1 = new short[bufferReadResult];
					System.arraycopy(buffer, 0, tmpBuf1, 0, bufferReadResult);
					//写入数据即播放
					audioTrack.write(tmpBuf1, 0, tmpBuf1.length);
					*/
                }
                audioTrack.stop();
                audioRecord.stop();
            }
            catch (Throwable t)
            {
            }
        }
    };

    class PlayingThread implements Runnable //extends Thread
    {
        public void run()
        {
            try
            {
                int x;
                mAudioTrack.play();//开始播放
                mAudioTrack.play();
                mAudioTrack.play();

                while (miPlaying)
                {
                    if(miPlayBufValid)
                    {
                        //x = ((mPlayBufWriteMarkIndex + mPlayBufWindownHalfLen) % mPlayBufWindownLen);
                        //mAudioTrack.write(mPlayBuf, x * mDatasPerFrame, mDatasPerFrame * mPlayBufWindownHalfLen);

                        //mAudioTrack.write(mPlayBuf, mPlayIndex * mDatasPerFrame, mDatasPerFrame);

                        x = mAudioTrack.write(mPlayBuf, mPlayIndex * mDatasPerFrame * mPlayBufFramesPerWindown, mDatasPerFrame * mPlayBufFramesPerWindown);
                        mPlayIndex++;
                        if(mPlayIndex >= mPlayBufWindowns)
                        {
                            mPlayIndex = 0;
                        }
                        mPlayCnt++;
                        //mAudioTrack.write(mPlayBuf, mPlayIndex * mDatasPerFrame * mPlayBufFramesPerWindown, mDatasPerFrame * mPlayBufFramesPerWindown);

                        //mtest1++;
                        //	Log.i(TAG, "play执行, write返回值  = " + x);
						/*
						mPlayIndex++;
						if(mPlayIndex >= (mPlayBufWindownLen / 2))
						{
							mPlayIndex = 0;
						}
						mAudioTrack.write(mPlayBuf, mPlayIndex * mDatasPerFrame * 2, mDatasPerFrame * 2);
						*/
                    }
                }
                mAudioTrack.stop();
            }
            catch (Throwable t)
            {
            }
        }
    };


    class PlayDataCheckThread implements Runnable //extends Thread
    {
        public void run()
        {
            try
            {
                int i;
                while (miPlaying)
                {
                    Thread.sleep(50);

                    if(mbCloseWavFile == true)
                    {
                        mbCloseWavFile = false;
                        mWavFileOpration.CloseWavData();
                    }

                    if((mTicks >= 4) && (miPlayBufValid == true))
                    {
                        Log.i(TAG, "200ms没有收到蓝牙数据，复位");
                        mTimeOutCnt++;
                        mTicks = 0;
                        mtest2++;
                        synchronized (mPlayBuf)
                        {
                            for(i = 0; i < mPlayBuf.length; i++)
                            {
                                mPlayBuf[i] = 0;
                            }
                        }

                        miPlayBufValid = false;
                        mPlayIndex = 0;
                        mWriteIndex = 0;

                        mtest1 = 0;
                        mtest2 = 0;

                        for(i = 0; i < mN; i++)
                        {
                            mPerDatasSrc[i] = 0;
                            mPerDatasFilter[i] = 0;
                        }
                    }
                    if(miPlayBufValid == true)
                    {
                        mTicks++;////
                    }
                }
            }
            catch (Throwable t)
            {
            }
        }
    };


    public void WriteData(short [] data, int len)
    {
        int i;
        int j;
        int temp;
        int dataTemp;
        int index;

        float delta;

        int perData;

        int indataLen = len * mFreDiff;
        short outdata[] = new short[indataLen];
        short intdata[] = new short[indataLen];

        Log.i(TAG, "WriteData, len = " + len);

        mTicks = 0;

        perData = mPerFrameLastData;
        mPerFrameLastData = intdata[len - 1];

        for(i = 0; i < len; i++)
        {
            for(j = 0; j < mFreDiff; j++)
            {//把频率填写完  mPerFrameLastData
                //intdata[mFreDiff * i + j] = data[i]; //直接复制，没有做线性拟合的
                delta = data[i] - perData;
                delta /= (float)mFreDiff;
                intdata[mFreDiff * i + j] = (short)(perData + delta * (j + 1));
            }
            perData = data[i];
        }
        Filter(intdata, outdata, mPerDatasSrc, mh1, indataLen, mN, mVol);//先低通滤波


        for(i = 0; i < mN; i++)
        {
            mPerDatasSrc[i] = intdata[indataLen - mN + i];//保存原始的数据,没倍频的用
        }

        if(mFreDoubles == 2)
        {
            for(i = 0; i < indataLen; i++)
            {
                intdata[i] = (short)Math.abs(outdata[i]);
            }
            Filter(intdata, outdata, mPerDatasFilter, mh2, indataLen, mN, 2);//倍频的滤波

            for(i = 0; i < mN; i++)
            {
                mPerDatasFilter[i] = intdata[indataLen - mN + i];//保存滤波后的数据，做第二次滤波用
            }
        }

        //String str = "";//实验储存数据
        //mPlayBufWindowns = 3;
        //static final int mPlayBufFramesPerWindown = 4;
        // 0 1 2 3 4 | 5 6 7 8 9 | 10 11 12 13 14
        if(miPlayBufValid == false)
        {
            Log.i(TAG, "miPlayBufValid == false " + mWriteIndex + "; mPlayIndex = " + mPlayIndex);
            if(mWriteIndex == 0)
            {
                mWriteIndex = mPlayBufFramesPerWindown;
                //mPlayIndex = 0;
            }
            else
            {
                mWriteIndex++;
                if(mWriteIndex >= (mPlayBufFramesPerWindown * mPlayBufWindowns))
                {
                    mWriteIndex = 0;
                }
            }
            for (i = 0; i < indataLen; i++)
            {
                mPlayBuf[mWriteIndex * mDatasPerFrame + i] = outdata[i];
            }
            miPlayBufValid = true;
        }
        else
        {
            Log.i(TAG, "miPlayBufValid == true " + mWriteIndex + "; mPlayIndex = " + mPlayIndex);
            mWriteIndex++;
            if(mWriteIndex >= (mPlayBufFramesPerWindown * mPlayBufWindowns))
            {
                mWriteIndex = 0;
            }

            //if((mPlayIndex * mPlayBufFramesPerWindown) == mWriteIndex)
            if((mWriteIndex / mPlayBufFramesPerWindown) == mPlayIndex)
            {
                //mWriteIndex = ((mPlayIndex + mPlayBufWindownHalfLen) % mPlayBufWindownHalfLen);
                mWriteIndex = (mPlayIndex + 1) * mPlayBufFramesPerWindown;
                if(mWriteIndex >= (mPlayBufFramesPerWindown * mPlayBufWindowns))
                {
                    mWriteIndex = 0;
                }
            }
            //-------------------------------------------

            for (i = 0; i < indataLen; i++)
            {
                mPlayBuf[mWriteIndex * mDatasPerFrame + i] = outdata[i];
            }
        }


    }

    void Filter(short indata[], short outdata[], short predata[], double h[], int indataLen, int firN, int vol)
    {
        int i;
        int n;
        int m;
        int temp;

        double ampl;

        double sum = 0;

        ampl = 1 + (vol - 1) * 0.5;

        int data[] = new int[indataLen + firN];
        for(i = 0; i < firN; i++)
        {
            //data[i] = predata[i] * vol;
            data[i] = (int)((double)predata[i] * ampl);

            if (data[i] > 32767)
            {
                data[i] = 32767;
            }
            else if (data[i] < -32767)
            {
                data[i] = -32767;
            }
        }

        for(i = firN; i < indataLen + firN; i++)
        {
            //data[i] = indata[i - firN] * vol;
            data[i] = (int)((double)indata[i - firN] * ampl);

            if (data[i] > 32767)
            {
                data[i] = 32767;
            }
            else if (data[i] < -32767)
            {
                data[i] = -32767;
            }
        }
		/*
		for (n = 0; n < firN; n++)
		{
			predata[n] = indata[indataLen - firN + n];
		}*/
        if(indataLen >= firN)
        {
            for (n = 0; n < firN; n++)
            {
                predata[n] = indata[indataLen - firN + n];
            }
        }
        else
        {
            temp = firN - indataLen;
            for(i = 0; i < temp; i++)
            {
                predata[i] = predata[i + indataLen];
            }

            for(n = 0; n < indataLen; n++)
            {
                predata[i] = indata[n];
                i++;
            }
        }


        for (n = 0; n < indataLen; n++)
        {
            sum = 0;
            for (m = 0; m < firN; m++)
            {
				/*if (n >= m)
				{
					sum += h[m] * indata[n - m];
				}
				else
				{
					sum += h[m] * predata[firN + n - m];
				}*/
                sum += h[m] * data[n - m + firN];
            }
            if (sum > 32767)
            {
                sum = 32767;
            }
            else if (sum < -32767)
            {
                sum = -32767;
            }
            outdata[n] = (short)sum;
        }
    }

    public void ShutDown()
    {
        miPlaying = false;
        miPlayBufValid = false;
        miRecording = false;
    }
}




